package rest

import (
	"fmt"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func ServeHttp(port uint16, bhs map[string]Bridge) {
	router := gin.Default()
	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", port),
		Handler: router,
	}

	router.Use(cors.New(cors.Config{
		AllowOrigins:     []string{"*"},
		AllowHeaders:     []string{"Content-Type", "Content-Length"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowMethods:     []string{http.MethodPost, http.MethodPut, http.MethodGet},
		AllowCredentials: true,
	}))

	group := router.Group("/api/npxy/v1")
	group.GET("/bridges", listBridge(bhs))
	group.POST("/bridges/:name/bindings", bind(bhs))

	go func() {
		if err := srv.ListenAndServe(); err != nil {
			log.Println(err)
		}
	}()
}

func bind(bhs map[string]Bridge) func(ctx *gin.Context) {
	return func(ctx *gin.Context) {
		req := BridgeBinding{}
		if err := ctx.ShouldBindJSON(&req); err != nil {
			ctx.AbortWithStatus(http.StatusBadRequest)
			return
		}
		addr := ctx.Param("name")
		if bh, ok := bhs[addr]; ok {
			if err := bh.Create(&req); err != nil {
				ctx.JSON(http.StatusUnavailableForLegalReasons, err.Error())
			} else {
				ctx.Status(http.StatusAccepted)
			}
		} else {
			ctx.Status(http.StatusNotFound)
		}
	}
}

func listBridge(bhs map[string]Bridge) func(ctx *gin.Context) {
	return func(ctx *gin.Context) {
		reps := make([]*BridgeInfo, 0, len(bhs))
		for _, bh := range bhs {
			reps = append(reps, bh.Get())
		}
		ctx.JSON(http.StatusOK, reps)
	}
}
